package cn.mengfly.testnrz.crazyIm.nettyserver;

import cn.mengfly.testnrz.crazyIm.ServerConstants;
import cn.mengfly.testnrz.curator.ZkClient;
import cn.mengfly.testnrz.json.JsonUtil;
import cn.mengfly.testnrz.util.ZookeeperUtil;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

/**
 * IM 节点的 Zk 协调客户端
 *
 * @author Mengfly
 */
public class ImWorker {

    /**
     * Zookeeper 客户端
     */
    private CuratorFramework client = null;

    /**
     * 保存当前ZNode节点的路径，创建后返回
     */
    private String pathRegistered = null;

    private final ImNode node = ImNode.getLocalInstance();

    private static ImWorker singleInstance = null;

    private ImWorker() {

    }

    public static ImWorker inst() {
        if (null == singleInstance) {
            synchronized (ImWorker.class) {
                if (null == singleInstance) {
                    singleInstance = new ImWorker();
                    singleInstance.client = ZkClient.inst().getClient();
                    singleInstance.init();
                }
            }
        }
        return singleInstance;
    }

    public void init() {
        createParentIfNeeded(ServerConstants.MANAGE_PATH);
        try {
            byte[] payload = JsonUtil.object2JsonBytes(node);
            pathRegistered = client.create()
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                    .forPath(ServerConstants.PATH_PREFIX, payload);
            // 为Node设置Id
            node.setId(ZookeeperUtil.getId(pathRegistered, ServerConstants.PATH_PREFIX));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public boolean incBalance() {
        if (null == node) {
            throw new RuntimeException("还没有设置Node节点");
        }
        // 增加负载，并写回Zookeeper
        try {
            node.getBalance().getAndIncrement();
            byte[] payload = JsonUtil.object2JsonBytes(node);
            client.setData().forPath(pathRegistered, payload);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 减少负载，标识有用户下线
     *
     * @return 是否减少成功
     */

    public boolean decrBalance() {
        if (null == node) {
            throw new RuntimeException("还没有设置Node节点");
        }
        // 减少负载，并写回Zookeeper
        try {
            node.getBalance().getAndDecrement();
            byte[] payload = JsonUtil.object2JsonBytes(node);
            client.setData().forPath(pathRegistered, payload);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 创建父节点
     */
    private void createParentIfNeeded(String managerPath) {
        try {
            Stat stat = client.checkExists().forPath(managerPath);
            if (null == stat) {
                client.create().creatingParentsIfNeeded().withProtection()
                        .withMode(CreateMode.PERSISTENT).forPath(managerPath);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
